/*
 * client_socket.h
 *
 *  Created on: 2021年1月27日
 *      Author: kimfeng
 */

#ifndef CLIENT_SOCKET_H_
#define CLIENT_SOCKET_H_

#include "asock_type.h"
#include "callback_handler.h"
#include "io_service_pool.h"
#include "pkg_parser.h"
#include <boost/array.hpp>

class client_socket
{
public:
	explicit client_socket(boost::asio::io_service& io_svc, const std::string& addr="", const std::string& port="");
	virtual ~client_socket();

	bool connect(const std::string& address, const std::string& port);
	void close();
	bool send_buffer(uchar *buf, std::size_t n);
	bool send_pkg(const sck_pkg_t &pkg);

	void attech_rsp_func(ushort req_num, CallbackFunction f)
	{
		m_handler.attech_callback_func(req_num, f);
	}

	void sck_pkg_new(sck_pkg_t *pkg, ushort req_num, ushort type, void *payload, std::size_t len);
	void sck_pkg_print(const sck_pkg_t& pkg);

	size_t sck_pkg_tobuf(const sck_pkg_t *pkg, uchar **buf);

	ushort get_magic() const { return m_magic; }
	void set_magic(ushort magic) { m_magic = magic; }
	ushort get_ver() const { return m_ver; }
	void set_ver(ushort ver) { m_ver = ver; }
	void set_reconnect(int val) { m_reconnect = val; }

protected:
	virtual void on_read_rsp(const sck_pkg_t& rsp){}
	virtual void on_connect(){}
	virtual void on_disconnect(){}

	boost::asio::ip::tcp::socket& socket(){ return m_sock; }

private:
	ushort m_magic, m_ver, m_seq;
	boost::array<uchar, 8192> m_buffer;

	boost::asio::ip::tcp::socket m_sock;

	callback_handler m_handler;
	std::string m_addr, m_port;

	pkg_parser m_parser;
	boost::asio::deadline_timer m_timer;
	sck_pkg_t m_pkg;
	vec_data_t m_payload;

	int m_reconnect;

	void handle_connect(const boost::system::error_code &e);
	void handle_read(const boost::system::error_code &e,
			std::size_t bytes_transferred);
	void handle_rd_timeout();
	void handle_write(const boost::system::error_code &e, void *buf);

	bool reconnect();
};

#endif /* CLIENT_SOCKET_H_ */
